import numpy as np
import copy
import matplotlib.pyplot as plt


def normalize_vector(vector):
    magnitude = np.linalg.norm(vector)
    normalized_vector = vector / magnitude
    return normalized_vector


class Bezier:
    def __init__(self, ps):
        self.ps = copy.deepcopy(ps)

    @staticmethod
    def __binomial_coefficient(n, k):
        coeff = 1
        for i in range(1, k + 1):
            coeff *= (n - i + 1) / i
        return coeff

    def interpolate(self, s):
        x = np.zeros_like(self.ps[0], dtype=float)
        n = len(self.ps) - 1
        for i in range(n + 1):
            coeff = Bezier.__binomial_coefficient(n, i)
            x += coeff * self.ps[i] * (1 - s) ** (n - i) * s ** i
        return x


if __name__ == "__main__":
    points = [np.array((0.0, 0.0)), np.array((0.5, 1.0)), np.array((1.0, 1.5)),
              np.array((1.5, 0.75)), np.array((2.0, 2.0))]
    num_points = 100

    s_values = np.linspace(0, 1, num_points)

    bezier = Bezier(points)
    interpolated_points = []
    for s in s_values:
        interpolated_points.append(tuple(bezier.interpolate(s)))
    plt.plot(*zip(*interpolated_points), label=f"{len(points) - 1} order Bezier curve")
    plt.scatter(*zip(*points), color='red', label='Control Points')
    plt.legend()
    plt.show()
